home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / clang / jcool01.zip / RANGE.H < prev    next >
C/C++ Source or Header  |  1992-11-20  |  8KB  |  202 lines

  1. /**** I shouldn't have redesigned this because the original syntax is
  2.       legal C++ (BC++ 3.1 and gcc don't support it yet, though).
  3.       --Jam, 11-19-92
  4. ****/
  5. //
  6. // Copyright (C) 1991 Texas Instruments Incorporated.
  7. //
  8. // Permission is granted to any individual or institution to use, copy, modify,
  9. // and distribute this software, provided that this complete copyright and
  10. // permission notice is maintained, intact, in all copies and supporting
  11. // documentation.
  12. //
  13. // Texas Instruments Incorporated provides this software "as is" without
  14. // express or implied warranty.
  15. //
  16. //
  17. // Created: MBN 08/21/89 -- Initial design and implementation
  18. // Updated: LGO 10/05/89 -- Make destructor inline
  19. // Updated: LGO 12/04/89 -- Efficiency re-write
  20. // Updated: DLS 03/27/91 -- New lite version
  21. // Updated: JAM 08/21/92 -- completely redesigned because modern template
  22. //                          do not support previous style
  23. //
  24. // The  parameterized  Range<Type,lbound,hbound> class is publicly derived from
  25. // the Range class  and supports arbitrary  user-defined ranges  for a type  of
  26. // object or built-in data type. This allows other higher level data structures
  27. // such as  the Vector and  List container classes  to  be parameterized over a
  28. // range of values for some  type so  that the programmer does  not have to add
  29. // bounds checking code to the application. A Vector  of positive integers, for
  30. // example, would  be easy  to declare, facilitating bounds checking restricted
  31. // to the code that implements the type, not the Vector.
  32. //
  33. // The  inclusive  upper and  lower   bounds for   the  range are  specified as
  34. // arguments  to the parameterized  type  declaration and  implementation macro
  35. // calls.   They are declared  as C++ constants  of  the  appropriate type.  No
  36. // storage is  allocated and all  references are compiled out by  the compiler.
  37. // Once  declared, a Range<Type,lbound,hbound> object cannot  have its upper or
  38. // lower bounds   changed,   since maintenance of all instances   would require
  39. // significant and unwarranted overhead.  Each Range<Type,lbound,hbound> object
  40. // has  a single private  data  slot that  holds ths instance value.  There are
  41. // three constructors.   The first is  a simple  empty  constructor. The second
  42. // accepts and sets an initial value.   The third  takes a reference to another
  43. // Range<Type,lbound,hbound> object and duplicates its value.
  44. //
  45. // All  Range<Type,lbound,hbound>  methods  are  implemented   as small  inline
  46. // functions to provide efficient encapsulation of objects,  including built-in
  47. // types such as int.  Methods are provided to get  the  lower and upper bounds
  48. // and set the value of the instance data  slot.  Assignment of  a value or one
  49. // object to another is supported by the overloaded operator= method.  Finally,
  50. // an implicit conversion  from a   Range<Type,lbound,hbound> object to a  Type
  51. // value is provided to allow mixed expressions.
  52. //
  53.  
  54. #ifndef RANGEH                    // If no Range class
  55. #define RANGEH
  56.  
  57. #include <iostream.h>
  58.  
  59. #include <cool/misc.h>
  60. #include <cool/Comparator.h>
  61.  
  62. #define COOL_DefineBoundsType(TYPE) \
  63. template <TYPE LOW, TYPE HIGH> \
  64. struct CoolBounds_##TYPE { \
  65.   typedef TYPE Type; \
  66.   inline static Type low()    /* Get low value range */ \
  67.     { return LOW; } \
  68.   inline static Type high()   /* Get high value range */ \
  69.     { return HIGH; } \
  70. }
  71.  
  72. COOL_DefineBoundsType(char);     // defines CoolBounds_char
  73. COOL_DefineBoundsType(int);      // defines CoolBounds_int
  74.  
  75. #define CoolRangeM(TYPE,LOW,HIGH) CoolRange< CoolBounds_##TYPE<LOW,HIGH> >
  76.  
  77. #define COOL_DefineRange(TYPE, LOW, HIGH, NAME) \
  78. struct CoolBounds_##NAME { \
  79.   typedef TYPE Type; \
  80.   static Type low() { return LOW; } \
  81.   static Type high() { return HIGH; } \
  82. }; \
  83. typedef CoolRange< CoolBounds_##NAME > NAME
  84.  
  85. template <class Bounds>
  86. class CoolRange : public Bounds {
  87. public:
  88.   CoolRange();     // Default ctor, initialize to lower bound
  89. //##  CoolRange(const Type& value); // Construct with value
  90.   // uses default copy-ctor and assignment operator
  91.   void operator=(const CoolRange& r) { this->data = r.data; } //## should not be necessary
  92.  
  93. //##  inline void set (const Type&);        // Set instance value
  94.  
  95. //##  inline operator Type () const;        // Implicit type conversion
  96.  
  97. //##   inline friend ostream& operator<<(ostream& os, const CoolRange<Bounds>& r);
  98. //##   inline friend istream& operator>>(istream& is, CoolRange<Bounds>& r);
  99. #ifndef COMPILERFIXED //##
  100.   CoolRange(const Bounds::Type& value) { this->set(value); }
  101.  
  102.   void set (const Bounds::Type& value) {
  103.      if (lessthan(value, low()) || greaterthan(value, high()))
  104.         this->report_set_error ();            // Raise exception
  105.      this->data = value;
  106.      }
  107.  
  108.    operator Bounds::Type() const {return this->data;}
  109.  
  110.    friend ostream& operator<<(ostream& os, const CoolRange<Bounds>& r)
  111.       { return os << r.data; }
  112.    friend istream& operator>>(istream& is, CoolRange<Bounds>& r) {
  113.       Type value;
  114.       if (is>>value)                // if input succeeds
  115.          if (CoolRange<Bounds>::lessthan(value, r.low())
  116.                || CoolRange<Bounds>::greaterthan(value, r.high()))
  117.             r.data = value;         // value is good
  118.          else
  119.             is.clear(ios::badbit);     // input value out of range
  120.       return is;
  121.       }
  122. #endif
  123. private:
  124.   Type data;                    // Storage for instance value
  125.  
  126.   void report_set_error () const;
  127.  
  128.   // convenient functions to test values
  129.   static int lessthan(const Type& a, const Type& b)
  130.     { return CoolComparator<Type>::lessthan(a,b); }
  131.   static int greaterthan(const Type& a, const Type& b)
  132.     { return !CoolComparator<Type>::lessthan(a,b); }
  133. };
  134.  
  135. // CoolRange<Bounds> -- Default constructor (no parameters)
  136. // Input:         None
  137. // Output:        None
  138. template<class Bounds>
  139. inline CoolRange<Bounds>::CoolRange() : data(low()) {}
  140.  
  141.  
  142. #ifdef COMPILERFIXED //##
  143.  
  144. // CoolRange<Bounds> -- Constructor with initial value
  145. // Input:         Reference to value
  146. // Output:        None
  147.  
  148. template<class Bounds>
  149. inline CoolRange<Bounds>::CoolRange(const Bounds::Type& value) {
  150.   this->set(value);
  151. }
  152.  
  153.  
  154. // set -- Set the value of the object
  155. // Input:  Value to set
  156. // Output: None
  157.  
  158. template<class Bounds>
  159. inline void CoolRange<Bounds>::set (const Bounds::Type& value) {
  160.   if (lessthan(value, low()) || greaterthan(value, high()))
  161.      this->report_set_error ();            // Raise exception
  162.   this->data = value;
  163. }
  164.  
  165. // operator Type() -- Provide implicit conversion to what ever type this 
  166. //                    class is parameterized over to allow mixed expressions
  167. // Input:             None
  168. // Output:            Value of object
  169.  
  170. template<class Bounds>
  171. inline CoolRange<Bounds>::operator Bounds::Type() const {return this->data;}
  172.  
  173.  
  174. // operator<< -- Overload output operator for CoolRange objects
  175. // Input:        CoolRange reference
  176. // Output:       Formatted output and stream descriptor
  177.  
  178. template<class Bounds>
  179. inline ostream& operator<<(ostream& os, const CoolRange<Bounds>& r) {
  180.    return os << r.data;
  181. }
  182.  
  183.  
  184. // operator>> -- Overload input operator for CoolRange objects
  185. // Input:        CoolRange reference
  186. // Output:       Formatted input and stream descriptor
  187.  
  188. template<class Bounds>
  189. inline istream& operator>>(istream& is, CoolRange<Bounds>& r) {
  190.    Type value;
  191.    if (is>>value)                // if input succeeds
  192.       if (lessthan(value, low()) || greaterthan(value, high()))
  193.          r.data = value;         // value is good
  194.       else
  195.          is.clear(ios::bad);     // input value out of range
  196.    return is;
  197. }
  198.  
  199. #endif   // FIXEDCOMPILER
  200.  
  201. #endif                        // End #ifdef of RANGEH
  202.